"""
呼叫客服任务处理模块
负责处理需要人工客服介入的请求
"""

import requests
import logging
import time
import uuid
from typing import Dict, Any, List
from config.settings import settings
from services.wx_api import WeChatAPI
import os

logger = logging.getLogger(__name__)

class CustomerServiceTask:
    """呼叫客服任务处理器（自动获取配置）"""
    
    def __init__(self):
        self.task_name = "呼叫客服"
        self.logger = logging.getLogger(f"{__name__}.CustomerServiceTask")
        self.service_keywords = ['人工', '客服', '转人工']
        # 从settings.py获取KF_ID
        self.open_kfid = settings.OPEN_KF_ID

    def can_handle(self, message: str, conversation_history: list) -> bool:
        """
        判断是否可以处理此消息（只判断关键词）
        """
        return any(keyword in message for keyword in self.service_keywords)

    def process(self, message: str, conversation_history: list, customer_id: str) -> Dict[str, Any]:
        """
        处理呼叫客服任务，将客户会话转接给企业员工，并发送客户消息和沟通摘要作为提示
        """
        self.logger.info(f"📞 开始处理呼叫客服任务 - 客户: {customer_id}")
        self.logger.info(f"📝 客户消息: {message}")
       
        try:
            last_message = message  # 如有历史可用 conversation_history[-1]
            
            # 获取客服应用的access_token（用于客服相关操作）
            kf_access_token = self.get_agent_access_token()
            if not kf_access_token:
                return {
                    "task_type": self.task_name,
                    "success": False,
                    "response": "获取客服access_token失败，无法转接人工客服"
                }
            
            # 获取企业应用的access_token（用于发送企业内部消息）
            corp_access_token = self.get_corp_access_token()
            if not corp_access_token:
                return {
                    "task_type": self.task_name,
                    "success": False,
                    "response": "获取企业access_token失败，无法发送内部消息"
                }
            
            # 先尝试获取客服人员列表（可能因为IP白名单失败）
            servicer_list = self.get_servicers(kf_access_token)
            if servicer_list:
                self.logger.info(f"✅ 获取到客服人员列表: {servicer_list}")
            else:
                self.logger.warning("⚠️ 无法获取客服人员列表，可能是IP白名单问题")
            
            # 选择第一个客服人员（通常是LiXingChen）
            target_servicer = servicer_list[0] if servicer_list else 'LiXingChen'
            self.logger.info(f"🎯 选择客服人员: {target_servicer}")
            
            # 转接客户会话给企业员工
            success, wx_response = self.forward_message_to_servicer(
                kf_access_token, 
                customer_id, 
                target_servicer, 
                last_message
            )
            
            if success:
                # 转接成功后，设置会话状态为人工服务
                from handlers.conversation_manager import ConversationManager
                conversation_manager = ConversationManager()
                conversation_manager.switch_to_human_service(customer_id)
                
                # 转接成功后，发送客户消息和沟通摘要给员工作为提示
                self.send_customer_message_to_servicer(
                    corp_access_token,  # 使用企业access_token发送内部消息
                    customer_id,
                    target_servicer,
                    last_message,
                    conversation_history
                )
                
                # 转接成功，给客户回复转接确认
                response_msg = f"已为您转接人工客服({target_servicer})，请稍候"
                if not servicer_list:
                    response_msg += "（注意：由于网络限制，客服可能无法立即响应，请耐心等待）"
                
                return {
                    "task_type": self.task_name,
                    "success": True,
                    "response": response_msg,
                    "customer_id": customer_id,
                    "message": message,
                    "servicer": target_servicer,
                    "warning": "IP白名单可能影响客服响应" if not servicer_list else None
                }
            else:
                return {
                    "task_type": self.task_name,
                    "success": False,
                    "response": "转接失败，请稍后再试",
                    "error": wx_response
                }
        except Exception as e:
            self.logger.error(f"❌ 呼叫客服任务处理失败: {str(e)}")
            return {
                "task_type": self.task_name,
                "success": False,
                "error": str(e),
                "response": "转接失败，请稍后再试"
            }

    def get_servicers(self, wx_access_token: str) -> list:
        """
        获取当前open_kfid下的所有“接待中”客服人员userid
        """
        url = f"https://qyapi.weixin.qq.com/cgi-bin/kf/servicer/list?access_token={wx_access_token}&open_kfid={self.open_kfid}"
        try:
            resp = requests.get(url, timeout=5)
            resp_json = resp.json()
            if resp_json.get("errcode", 1) == 0:
                # 只返回接待中的userid
                return [
                    servicer["userid"]
                    for servicer in resp_json.get("servicer_list", [])
                    if "userid" in servicer and servicer.get("status", 1) == 0
                ]
            else:
                self.logger.error(f"获取客服人员失败: {resp_json}")
                return []
        except Exception as e:
            self.logger.error(f"获取客服人员异常: {str(e)}")    
            return []
    def send_text_message(self, wx_access_token: str, external_userid: str, content: str, msgid: str = None) -> (bool, str):
        """
        发送文本消息给指定微信客户（参考官方文档：https://developer.work.weixin.qq.com/document/path/94674）
        参数：
            wx_access_token: 企业微信access_token
            external_userid: 客户的external_userid
            content: 文本内容
            msgid: 可选，消息ID，需保证唯一性（不传则由系统生成）
        返回：
            (True, resp_json) 或 (False, 错误信息)
        用法示例：
            success, resp = self.send_text_message(wx_access_token, external_userid, "你好")
        """
        url = f"https://qyapi.weixin.qq.com/cgi-bin/kf/send_msg?access_token={wx_access_token}"
        payload = {
            "touser": external_userid,
            "open_kfid": self.open_kfid,
            "msgtype": "text",
            "text": {
                "content": content
            }
        }
        if msgid:
            payload["msgid"] = msgid
        
        # 添加详细日志
        self.logger.info(f"📤 准备发送客服消息:")
        self.logger.info(f"   URL: {url}")
        self.logger.info(f"   external_userid: {external_userid}")
        self.logger.info(f"   open_kfid: {self.open_kfid}")
        self.logger.info(f"   content: {content}")
        self.logger.info(f"   payload: {payload}")
        
        try:
            resp = requests.post(url, json=payload, timeout=10)
            self.logger.info(f"📡 HTTP响应状态码: {resp.status_code}")
            self.logger.info(f"📡 HTTP响应内容: {resp.text}")
            
            resp_json = resp.json()
            if resp_json.get("errcode", 1) == 0:
                self.logger.info(f"✅ 客服消息发送成功: {resp_json}")
                return True, resp_json
            else:
                error_msg = f"❌ 客服消息发送失败: {resp_json}"
                self.logger.error(error_msg)
                return False, resp_json
        except Exception as e:
            error_msg = f"❌ 发送客服消息异常: {str(e)}"
            self.logger.error(error_msg)
            return False, str(e) 

    def get_service_state(self, wx_access_token: str, external_userid: str) -> dict:
        """
        获取客户会话状态
        
        Args:
            wx_access_token: 企业微信access_token
            external_userid: 客户的external_userid
        返回：
            dict: 会话状态信息
        """
        try:
            url = f"https://qyapi.weixin.qq.com/cgi-bin/kf/service_state/get?access_token={wx_access_token}"
            params = {
                'external_userid': external_userid,
                'open_kfid': self.open_kfid
            }
            
            self.logger.info(f"📊 获取客户会话状态...")
            self.logger.info(f"   external_userid: {external_userid}")
            self.logger.info(f"   open_kfid: {self.open_kfid}")
            
            resp = requests.get(url, params=params, timeout=10)
            self.logger.info(f"📡 HTTP响应状态码: {resp.status_code}")
            self.logger.info(f"📡 HTTP响应内容: {resp.text}")
            
            resp_json = resp.json()
            if resp_json.get("errcode") == 0:
                self.logger.info(f"✅ 获取会话状态成功: {resp_json}")
                return resp_json
            else:
                self.logger.error(f"❌ 获取会话状态失败: {resp_json}")
                return resp_json
        except Exception as e:
            self.logger.error(f"❌ 获取会话状态异常: {str(e)}")
            return {"errcode": -1, "errmsg": str(e)}

    def forward_message_to_servicer(self, wx_access_token: str, external_userid: str, servicer_userid: str, content: str, msgid: str = None) -> (bool, str):
        """
        将客户消息转发给企业员工
        
        Args:
            wx_access_token: 企业微信access_token
            external_userid: 客户的external_userid
            servicer_userid: 企业员工userid
            content: 客户消息内容
            msgid: 可选，消息ID，需保证唯一性（不传则由系统生成）
        返回：
            (True, resp_json) 或 (False, 错误信息)
        """
        # 先获取当前会话状态
        state_info = self.get_service_state(wx_access_token, external_userid)
        
        # 如果获取状态失败，尝试直接转接
        if state_info.get("errcode") != 0:
            self.logger.warning("⚠️ 无法获取会话状态，尝试直接转接")
        
        # 使用客服会话转接功能
        url = f"https://qyapi.weixin.qq.com/cgi-bin/kf/service_state/trans?access_token={wx_access_token}"
        
        # 构建转接请求 - 根据企业微信官方文档调整参数
        payload = {
            "external_userid": external_userid,
            "open_kfid": self.open_kfid,
            "servicer_userid": servicer_userid,
            "service_state": 3  # 3表示转接给指定客服
        }
        
        # 添加详细日志
        self.logger.info(f"📤 准备转接客户会话给企业员工:")
        self.logger.info(f"   URL: {url}")
        self.logger.info(f"   servicer_userid: {servicer_userid}")
        self.logger.info(f"   external_userid: {external_userid}")
        self.logger.info(f"   open_kfid: {self.open_kfid}")
        self.logger.info(f"   service_state: 3")
        self.logger.info(f"   payload: {payload}")
        
        try:
            resp = requests.post(url, json=payload, timeout=10)
            self.logger.info(f"📡 HTTP响应状态码: {resp.status_code}")
            self.logger.info(f"📡 HTTP响应内容: {resp.text}")
            
            resp_json = resp.json()
            if resp_json.get("errcode", 1) == 0:
                self.logger.info(f"✅ 客户会话转接成功: {resp_json}")
                return True, resp_json
            else:
                error_msg = f"❌ 客户会话转接失败: {resp_json}"
                self.logger.error(error_msg)
                return False, resp_json
        except Exception as e:
            error_msg = f"❌ 转接客户会话异常: {str(e)}"
            self.logger.error(error_msg)
            return False, str(e)

    def get_corp_access_token(self) -> str:
        """
        获取企业微信企业应用的access_token（用于发送企业内部消息）
        """
        try:
            # 使用企业应用的Secret
            corp_secret = os.getenv('WX_CORPSECRET')
            if not corp_secret:
                self.logger.error("❌ WX_CORPSECRET 未配置，无法获取企业access_token")
                return None
            
            corp_id = os.getenv('WX_CORPID')
            if not corp_id:
                self.logger.error("❌ WX_CORPID 未配置，无法获取企业access_token")
                return None
            
            url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken"
            params = {
                'corpid': corp_id,
                'corpsecret': corp_secret
            }
            
            self.logger.info(f"🔑 获取企业access_token...")
            self.logger.info(f"   corp_id: {corp_id}")
            self.logger.info(f"   corp_secret: {corp_secret[:6]}***（已隐藏）")
            
            resp = requests.get(url, params=params, timeout=10)
            resp_json = resp.json()
            
            if resp_json.get("errcode") == 0:
                access_token = resp_json.get("access_token")
                self.logger.info(f"✅ 获取企业access_token成功")
                return access_token
            else:
                self.logger.error(f"❌ 获取企业access_token失败: {resp_json}")
                return None
        except Exception as e:
            self.logger.error(f"❌ 获取企业access_token异常: {str(e)}")
            return None

    def get_agent_access_token(self) -> str:
        """
        获取企业微信客服应用的access_token（用于客服相关操作）
        这里需要根据实际情况配置正确的应用Secret
        """
        try:
            # 从环境变量获取客服应用Secret
            agent_secret = os.getenv('WX_AGENT_SECRET')
            if not agent_secret:
                self.logger.error("❌ WX_AGENT_SECRET 未配置，无法获取客服应用access_token")
                return None
            
            corp_id = os.getenv('WX_CORPID')
            if not corp_id:
                self.logger.error("❌ WX_CORPID 未配置，无法获取客服应用access_token")
                return None
            
            url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken"
            params = {
                'corpid': corp_id,
                'corpsecret': agent_secret
            }
            
            self.logger.info(f"🔑 获取客服应用access_token...")
            self.logger.info(f"   corp_id: {corp_id}")
            self.logger.info(f"   agent_secret: {agent_secret[:6]}***（已隐藏）")
            
            resp = requests.get(url, params=params, timeout=10)
            resp_json = resp.json()
            
            if resp_json.get("errcode") == 0:
                access_token = resp_json.get("access_token")
                self.logger.info(f"✅ 获取客服应用access_token成功")
                return access_token
            else:
                self.logger.error(f"❌ 获取客服应用access_token失败: {resp_json}")
                return None
        except Exception as e:
            self.logger.error(f"❌ 获取客服应用access_token异常: {str(e)}")
            return None

    def get_agent_list(self, access_token: str) -> list:
        """
        获取企业微信应用列表
        """
        try:
            url = "https://qyapi.weixin.qq.com/cgi-bin/agent/list"
            params = {'access_token': access_token}
            
            resp = requests.get(url, params=params, timeout=10)
            resp_json = resp.json()
            
            if resp_json.get("errcode") == 0:
                agent_list = resp_json.get("agentlist", [])
                self.logger.info(f"✅ 获取到应用列表: {len(agent_list)} 个应用")
                for agent in agent_list:
                    self.logger.info(f"   - agentid: {agent.get('agentid')}, name: {agent.get('name')}")
                return agent_list
            else:
                self.logger.error(f"❌ 获取应用列表失败: {resp_json}")
                return []
        except Exception as e:
            self.logger.error(f"❌ 获取应用列表异常: {str(e)}")
            return []

    def get_agent_id(self) -> str:
        """
        获取企业微信应用ID
        这里需要根据实际情况配置
        """
        # 可以从配置文件或环境变量获取
        return getattr(settings, 'WX_AGENT_ID', '1000002')  # 默认值 

    def send_customer_message_to_servicer(self, wx_access_token: str, external_userid: str, servicer_userid: str, customer_message: str, conversation_history: list = None) -> bool:
        """
        将客户消息和沟通摘要发送给企业员工作为提示
        
        Args:
            wx_access_token: 企业微信access_token
            external_userid: 客户的external_userid
            servicer_userid: 企业员工userid
            customer_message: 客户消息内容
            conversation_history: 对话历史，用于提取沟通摘要
        返回：
            bool: 发送是否成功
        """
        try:
            # 检查access_token是否有效
            if not wx_access_token:
                self.logger.error("❌ access_token为空，无法发送消息")
                return False
            
            # 使用企业微信内部消息接口发送给企业员工
            url = f"https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token={wx_access_token}"
            
            # 构建提示消息内容
            prompt_content = f"🔔 客户消息提示:\n\n客户ID: {external_userid}\n客户最新消息: {customer_message}\n\n"
            
            # 添加沟通摘要
            if conversation_history and len(conversation_history) > 0:
                prompt_content += "📋 沟通摘要:\n"
                for i, summary in enumerate(conversation_history, 1):
                    if isinstance(summary, dict) and "沟通摘要" in summary:
                        # 如果是包含沟通摘要的字典
                        summaries = summary.get("沟通摘要", [])
                        for j, item in enumerate(summaries, 1):
                            prompt_content += f"{j}. {item}\n"
                    elif isinstance(summary, str):
                        # 如果是字符串，直接添加
                        prompt_content += f"{i}. {summary}\n"
                    else:
                        # 其他类型，转换为字符串
                        prompt_content += f"{i}. {str(summary)}\n"
                prompt_content += "\n"
            
            prompt_content += "请及时回复客户。"
            
            payload = {
                "touser": servicer_userid,  # 企业员工userid
                "msgtype": "text",
                "agentid": self.get_agent_id(),  # 需要获取应用ID
                "text": {
                    "content": prompt_content
                }
            }
            
            # 添加详细日志
            self.logger.info(f"📤 准备发送客户消息和沟通摘要给企业员工:")
            self.logger.info(f"   URL: {url}")
            self.logger.info(f"   servicer_userid: {servicer_userid}")
            self.logger.info(f"   external_userid: {external_userid}")
            self.logger.info(f"   agentid: {self.get_agent_id()}")
            self.logger.info(f"   content: {prompt_content}")
            self.logger.info(f"   payload: {payload}")
            
            resp = requests.post(url, json=payload, timeout=10)
            self.logger.info(f"📡 HTTP响应状态码: {resp.status_code}")
            self.logger.info(f"📡 HTTP响应内容: {resp.text}")
            
            resp_json = resp.json()
            if resp_json.get("errcode") == 0:
                self.logger.info(f"✅ 客户消息和沟通摘要发送成功: {resp_json}")
                return True
            elif resp_json.get("errcode") == 301002:
                self.logger.error(f"❌ 权限错误：当前access_token无权操作agentid {self.get_agent_id()}")
                self.logger.error(f"   请检查WX_AGENT_SECRET配置是否正确")
                return False
            else:
                self.logger.error(f"❌ 客户消息和沟通摘要发送失败: {resp_json}")
                return False
        except Exception as e:
            self.logger.error(f"❌ 发送客户消息和沟通摘要异常: {str(e)}")
            return False 